package cn.geminis.warehouse.service.delivery.controller;

import cn.geminis.warehouse.service.delivery.entity.Delivery;
import cn.geminis.warehouse.service.delivery.entity.DeliveryDetail;
import cn.geminis.warehouse.service.delivery.entity.repository.DeliveryDetailRepository;
import cn.geminis.workflow.client.Approve;
import cn.geminis.workflow.client.WorkflowClient;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class DeliveryController {

    private final String PROCESS_KEY = "wh_delivery";
    private final String TASK_LOAD_KEY = "wh_delivery_load";
    private final String TASK_TRANSIT_KEY = "wh_delivery_transit";

    private final WorkflowClient workflowClient;
    private final DeliveryDetailRepository deliveryDetailRepository;

    private void completeTask(String taskKey, String[] ids) {
        Arrays.stream(ids).forEach(id -> {
            workflowClient.taskAssignee(id, null);
            workflowClient.taskComplete(
                    Approve.builder()
                            .result("agree")
                            .taskKey(taskKey)
                            .businessKey(id)
                            .build());
        });
    }

    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public void save(@RequestBody Delivery object) {
        var details = new HashMap<String, DeliveryDetail>();
        for (var detail : object.getDetails()) {
            var exist = details.get(detail.getProductBatch().getId());
            if (ObjectUtils.isEmpty(exist)) {
                details.put(detail.getProductBatch().getId(), detail);
            } else {
                exist.setAmount(exist.getAmount() + detail.getAmount());
                detail.setAmount(0);
            }
            detail.setDelivery(object);
        }
        for (var route : object.getRoutes()) {
            route.setDelivery(object);
        }
        object.getDetails().removeIf(detail -> detail.getAmount() == 0 && ObjectUtils.isEmpty(detail.getId()));
        object.getDetails().forEach(detail -> {
            if (detail.getAmount() == 0) {
                this.deliveryDetailRepository.delete(detail);
                object.getDetails().remove(detail);
            }
        });
        var newOrder = ObjectUtils.isEmpty(object.getId());
        this.repository.save(object);
        if (newOrder) {
            workflowClient.processStart(PROCESS_KEY, object.getId(), object);
        }
    }

    @DeleteMapping
    @Transactional(rollbackFor = Exception.class)
    public void delete(@RequestBody List<String> ids) {
        ids.forEach((id) -> {
            this.repository.deleteById(id);
            workflowClient.processStop(PROCESS_KEY, id);
        });
    }

    @PostMapping("/load")
    @Transactional(rollbackFor = Exception.class)
    public void load(@RequestParam String[] ids, @RequestParam String time) {
        this.repository.load(LocalDate.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd")), ids);
        completeTask(TASK_LOAD_KEY, ids);
    }

    @PostMapping("/transit")
    @Transactional(rollbackFor = Exception.class)
    public void transit(@RequestParam String[] ids, @RequestParam String time) {
        this.repository.transit(LocalDate.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd")), ids);
        completeTask(TASK_TRANSIT_KEY, ids);
    }
}
